package com.wutong.eams.utils;

import com.wutong.eams.config.JwtConfig;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;

import javax.crypto.SecretKey;
import java.util.Date;
import java.util.Map;

public class JwtUtil {

    private static final SecretKey SECRET_KEY = Keys.hmacShaKeyFor(JwtConfig.SECRET.getBytes());

    public static String generateToken(String subject, Map<String, Object> claims, long expirationTime) {
        return Jwts.builder()
                .subject(subject)
                .encodePayload(true)
                .claims(claims)
                .expiration(new Date(System.currentTimeMillis() + expirationTime))
                .signWith(SECRET_KEY)
                .issuedAt(new Date())
                .compact();
    }

    public static <R> R parseToken(String token, JwtExceptionHandel<R> exceptionHandler) {
        try {
            Claims claims = Jwts.parser()
                    .verifyWith(SECRET_KEY)
                    .build()
                    .parseSignedClaims(token)
                    .getPayload();
            return exceptionHandler.commonHandler(claims);
        } catch (ExpiredJwtException e) {
            return exceptionHandler.expiredHandler(e);
        } catch (IllegalArgumentException e) {
            return exceptionHandler.invalidHandler(e);
        } catch (Exception e) {
            return exceptionHandler.otherHandler(e);
        }
    }

    // JWT 异常处理接口，可返回指定类型对象
    public interface JwtExceptionHandel<R> {
        //未出现异常时，处理claims
        R commonHandler(Claims claims) throws Exception;

        // 出现TOKEN过期异常时，处理异常
        R expiredHandler(ExpiredJwtException e);

        // 出现TOKEN验证失败异常时，处理异常
        R invalidHandler(IllegalArgumentException e);

        // 出现其他异常时，处理异常
        R otherHandler(Exception e);
    }

    // JWT 异常处理接口（简化，全部异常当成一种异常处理）
    public interface JwtDefaultExceptionHandel<R> extends JwtExceptionHandel<R> {
        @Override
        default R expiredHandler(ExpiredJwtException e) {
            return null;
        }

        @Override
        default R invalidHandler(IllegalArgumentException e) {
            return null;
        }

        @Override
        default R otherHandler(Exception e) {
            return null;
        }

        R allHandler(Exception e);
    }
}
